/**
 * @file LogEvent.h
 * @author  haifeng (haifengxiao@icloud.com)
 * @brief
 * @version 0.1
 * @date 2021-07-06
 *
 * @copyright Copyright (c) 2021
 *
 */

#pragma once

#include <stdint.h>
#include <memory>
#include <string>
#include <sstream>

#include "LogLevel.h"

namespace Chen {
    namespace Log {

        class Logger;

        class LogEvent {
        public:
            typedef std::shared_ptr<LogEvent> ptr;

            /**
             * @brief Construct a new Log Event object
             *
             * @param logger
             * @param level
             * @param file
             * @param line
             * @param elapsa
             * @param thread_id
             * @param fiber_id
             * @param time
             * @param thread_name
             */
            LogEvent(std::shared_ptr<Logger> logger, LogLevel::Level level
                , const char* file, int32_t line, uint32_t elapsa
                , uint32_t thread_id, uint32_t fiber_id, uint64_t time
                , const std::string& thread_name);

            /**
             * @brief Get the Level object
             *
             * @return LogLevel
             */
            LogLevel::Level getLevel() const { return m_level; }

            /**
             * @brief Get the File object
             *
             * @return char*
             */
            const char* getFile() const { return m_file; }

            /**
             * @brief Get the Line object
             *
             * @return int32_t
             */
            int32_t getLine() const { return m_line; }

            /**
             * @brief Get the Elapse object
             *
             * @return int32_t
             */
            int32_t getElapse() const { return m_elapse; }

            /**
             * @brief Get the Thread Id object
             *
             * @return uint32_t
             */
            uint32_t getThreadId() const { return m_threadId; }

            /**
             * @brief Get the Fiber Id object
             *
             * @return uint32_t
             */
            uint32_t getFiberId() const { return m_fiberId; }

            /**
             * @brief Get the Time object
             *
             * @return uint64_t
             */
            uint64_t getTime() const { return m_time; }

            /**
             * @brief Get the Thread Name object
             *
             * @return std::string
             */
            std::string getThreadName() const { return m_threadName; }

            /**
             * @brief Get the Content object
             *
             * @return std::string
             */
            std::string getContent() const { return m_ss.str(); }

            /**
             * @brief Get the Logger object
             *
             * @return std::shared_ptr<Logger>
             */
            std::shared_ptr<Logger> getLogger() const { return m_logger; }

            /**
             * @brief
             *
             * @return std::stringstream&
             */
            std::stringstream& getSS() { return m_ss; }

            /**
             * @brief Log Formatted
             *
             * @param fmt Format pattern
             * @param ...
             */
            void format(const char* fmt, ...);

            /**
             * @brief Log Formatted
             *
             * @param fmt Format pattern
             * @param al
             */
            void format(const char* fmt, va_list al);

        private:
            std::shared_ptr<Logger> m_logger;
            LogLevel::Level m_level;
            const char* m_file = nullptr;
            int32_t m_line = 0;
            int32_t m_elapse = 0;
            uint32_t m_threadId = 0;
            uint32_t m_fiberId = 0;
            uint64_t m_time = 0;
            std::string m_threadName;
            std::stringstream m_ss;
        };

    }//namespace Log
}//namespace Chen